Skip to content

Add TransformFunctionProvider to DynamicConfigTransformer#6881

Merged
kkondaka merged 8 commits into
opensearch-project:mainfrom
kkondaka:dyn-config-xfmr
May 28, 2026
Merged

Add TransformFunctionProvider to DynamicConfigTransformer#6881
kkondaka merged 8 commits into
opensearch-project:mainfrom
kkondaka:dyn-config-xfmr

Conversation

@kkondaka

Copy link
Copy Markdown
Collaborator

Description

This PR introduces a type-safe mechanism for dynamically invoking transformation functions during
pipeline template resolution. Previously, utility methods (e.g., calculateDepth, getAccountIdFromRole)
lived directly in DynamicConfigTransformer and were invoked reflectively on this. This was fragile,
untestable in isolation, and violated separation of concerns.

Changes
New API contracts (data-prepper-api):
• PipelineTransformFunctionProvider — marker interface that classes must implement to be valid function providers
• @TransformationFunction — method-level annotation marking methods as callable from template YAML FUNCTION_NAME placeholders

Externalized functions (data-prepper-plugins/aws-plugin):
• Created PipelineTransformFunctions with all 5 static utility methods (calculateDepth, calculateDepthForRdsSource, getSourceCoordinationIdentifierEnvVariable, getIncludePrefixForRdsSource, getAccountIdFromRole)
• Each method is public static, annotated with @TransformationFunction, and the class implements PipelineTransformFunctionProvider

Rule model changes (data-prepper-pipeline-parser):
• Added function_providers field to RuleTransformerModel (deserialized from rule YAML)
• Threaded functionProviders through RuleFileEvaluation → RuleEvaluatorResult → DynamicConfigTransformer
• invokeMethod() now validates:

  1. The class implements PipelineTransformFunctionProvider
  2. The method is annotated with @TransformationFunction
  3. Invokes statically via method.invoke(null, arg)

Rule YAML updates:
• Added function_providers to all production rule files (rds-rule.yaml, rds-joins-rule.yaml, mongodb-rule.yaml, documentdb-rule.yaml)

Issues Resolved

Resolves #[Issue number to be closed when this PR is merged]

Check List

  • [X ] New functionality includes testing.
  • New functionality has a documentation issue. Please link to it in this PR.
    • New functionality has javadoc added
  • [ X] Commits are signed with a real name per the DCO

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Signed-off-by: Kondaka <krishkdk@amazon.com>
@github-actions

github-actions Bot commented May 22, 2026

Copy link
Copy Markdown

✅ License Header Check Passed

All newly added files have proper license headers. Great work! 🎉

kkondaka added 3 commits May 22, 2026 08:16
Signed-off-by: Kondaka <krishkdk@amazon.com>
Signed-off-by: Kondaka <krishkdk@amazon.com>
Signed-off-by: Kondaka <krishkdk@amazon.com>
Comment thread data-prepper-plugins/aws-plugin/build.gradle Outdated

private Class<?> resolveClassForMethod(final List<String> functionProviders, String methodName, Class<?> parameterType) throws ReflectiveOperationException {
if (functionProviders.size() == 1) {
return Class.forName(functionProviders.get(0));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use this instead:

Class.forName(className, false, this.getClass().getClassLoader());

It will not run any static initializers. This let's us check that this is supposed to be a function.

Signed-off-by: Kondaka <krishkdk@amazon.com>
// Inner test helper classes for invokeMethod validation tests
private static final String PROVIDER_PKG = "org.opensearch.dataprepper.pipeline.parser.transformer.dataprepper_transformer.";

// --- invokeMethod: Happy path ---

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop these dangling comments.

protected String getSourceCoordinationIdentifier() {
return System.getenv(SOURCE_COORDINATION_IDENTIFIER_ENVIRONMENT_VARIABLE);
}
public Object invokeMethod(final List<String> functionProviders, String methodName, Class<?> parameterType, Object arg) throws ReflectiveOperationException {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be private or package-private.

DynamicConfigTransformer transformer = new DynamicConfigTransformer(ruleEvaluator);
assertThat(transformer.getAccountIdFromRole(testRoleArn)).isEqualTo(testAccountId);
List<String> providers = Collections.singletonList(
"org.opensearch.dataprepper.pipeline.parser.transformer.DynamicConfigTransformerTest$ValidProviderNoAnnotation");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to fail simply by being in the wrong package name. You need this to be in a package with dataprepper_transformers.

assertThat(transformer.getAccountIdFromRole(testRoleArn)).isNull();
List<String> providers = Collections.singletonList(
"org.opensearch.dataprepper.pipeline.parser.transformer.DynamicConfigTransformerTest$ValidProviderNoAnnotation");
assertThrows(Exception.class, () ->

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to look at the message of the exception and verify it contains at least a little bit of the expected string. This would have shown that this wasn't testing what you expected.

kkondaka added 2 commits May 27, 2026 15:02
Signed-off-by: Kondaka <krishkdk@amazon.com>
Signed-off-by: Kondaka <krishkdk@amazon.com>
Signed-off-by: Kondaka <krishkdk@amazon.com>
@kkondaka kkondaka merged commit fbca3db into opensearch-project:main May 28, 2026
71 of 73 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants